package org.qloudgen.txn.dilithium.cluster.beans;

import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.ibatis.session.SqlSession;
import org.qloudgen.txn.dilithium.cluster.common.CommonValues;
import org.qloudgen.txn.dilithium.cluster.common.ExecShellCommand;
import org.qloudgen.txn.dilithium.cluster.common.Validation;
import org.qloudgen.txn.dilithium.cluster.sqlmap.ConfigNames;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class Cluster implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String userNo;
	private int clusterID;
	private String clusterName;
	private String clusterDesc;
	private String clusterStatus;
	private String createTime;
	private String startTime;
	private String gtmMasterIp;
	private String gtmSlaveIp;
	private String sysUser;
	private String sysUserPassword;
	private String DBSuperuserPassword;
//	private String rootPassword;
	private int nodeNumber;
	private String controllerIp;
	private String nodeIps;
	private List<String> nodeIpsList;
	private String newNodeIp;
	private String radioChoice;
	
	public int getClusterID() {
		return clusterID;
	}
	public Cluster setClusterID(int clusterID) {
		this.clusterID = clusterID;
		return this;
	}
	public String getClusterName() {
		return clusterName;
	}
	public void setClusterName(String clusterName) {
		this.clusterName = clusterName;
	}
	public String getClusterDesc() {
		return clusterDesc;
	}
	public void setClusterDesc(String clusterDesc) {
		this.clusterDesc = clusterDesc;
	}
	public String getClusterStatus() {
		return clusterStatus;
	}
	public Cluster setClusterStatus(String clusterStatus) {
		this.clusterStatus = clusterStatus;
		return this;
	}
	public String getCreateTime() {
		return createTime;
	}
	public void setCreateTime(String createTime) {
		this.createTime = createTime;
	}
	public String getStartTime() {
		return startTime;
	}
	public void setStartTime(String startTime) {
		this.startTime = startTime;
	}
	public String getGtmMasterIp() {
		return gtmMasterIp;
	}
	public void setGtmMasterIp(String gtmMasterIp) {
		this.gtmMasterIp = gtmMasterIp;
	}
	public String getGtmSlaveIp() {
		return gtmSlaveIp;
	}
	public void setGtmSlaveIp(String gtmSlaveIp) {
		this.gtmSlaveIp = gtmSlaveIp;
	}
	public String getSysUser() {
		return sysUser;
	}
	public void setSysUser(String sysUser) {
		this.sysUser = sysUser;
	}
	public String getSysUserPassword() {
		return sysUserPassword;
	}
	public void setSysUserPassword(String sysUserPassword) {
		this.sysUserPassword = sysUserPassword;
	}
//	public String getRootPassword() {
//		return rootPassword;
//	}
//	public void setRootPassword(String rootPassword) {
//		this.rootPassword = rootPassword;
//	}
	public int getNodeNumber() {
		return nodeNumber;
	}
	public void setNodeNumber(int nodeNumber) {
		this.nodeNumber = nodeNumber;
	}
	public String getNodeIps() {
		return nodeIps;
	}
	public void setNodeIps(String nodeIps) {
		this.nodeIps = nodeIps;
	}
	public String getUserNo() {
		return userNo;
	}
	public void setUserNo(String userNo) {
		this.userNo = userNo;
	}
	
	public String checkClusterInfo() {
		
		StringBuffer sb = new StringBuffer();
		Set<String> ipSet = new HashSet<String>();
		
		// check cluster name
		String ret = checkClusterName();
		if (ret != null) sb.append(ret+"\n");
		
		//check controller ip
		ret = checkNodeIp(this.getControllerIp());
		if (ret != null) sb.append(ret+"\n");
		ipSet.add(this.getControllerIp());
		
		//check GTM master ip
		ret = checkNodeIp(this.getGtmMasterIp());
		if (ret != null) sb.append(ret+"\n");
		if (this.getGtmMasterIp() != null) ipSet.add(this.getGtmMasterIp());
		
		//check GTM slave ip
		if (this.getGtmSlaveIp() != null && !this.getGtmSlaveIp().equals("")){
			ret = checkNodeIp(this.getGtmSlaveIp());
			if (ret != null) sb.append(ret+"\n");
			ipSet.add(this.getGtmSlaveIp());
		}
		
		//check node ips
		if (this.getNodeIps() != null){
			String[] ips = this.getNodeIps().split("\n");
			trimArray(ips);
			nodeIpsList = Lists.newArrayList();
			
			for (int i = 0; i<ips.length; i++){			
				if (ips[i] != null){
					ret = checkNodeIp(ips[i]);
					if (ret != null) sb.append(ret+"\n");
					nodeIpsList.add(ips[i]);
					ipSet.add(ips[i]);
				}
			}
		}
		
		int gtmNumber = 0;
		if (this.getGtmMasterIp() != null) { gtmNumber = 1;	}
		if (this.getGtmSlaveIp() != null) { gtmNumber = 2;	}
		
		//check ip if unique
		if (ipSet.size() != ((nodeIpsList != null) ? nodeIpsList.size():0) + gtmNumber + 1) 
			sb.append(" all ips are not unique!\n");		
		
//		//check root password
//		ret = checkPassword(this.getControllerIp(),"root",this.getRootPassword());
//		if (ret != null) sb.append(ret+"\n");
		
//		ret = checkPassword(this.getGtmMasterIp(),"root",this.getRootPassword());
//		if (ret != null) sb.append(ret+"\n");
//		
//		if (this.getGtmSlaveIp() != null && !this.getGtmSlaveIp().equals("")){
//			ret = checkPassword(this.getGtmSlaveIp(),"root",this.getRootPassword());
//			if (ret != null) sb.append(ret+"\n");
//		}
//		
//		if (nodeIpsList != null) {
//			for (String nodeIp : nodeIpsList){
//				ret = checkPassword(nodeIp,"root",this.getRootPassword());
//				if (ret != null) sb.append(ret+"\n");
//			}
//		}
		
		//check sysuser and password
		ret = checkSysUser(this.getControllerIp());
		if (ret != null) sb.append(ret+"\n");
		
		ret = checkSysUser(this.getGtmMasterIp());
		if (ret != null) sb.append(ret+"\n");
		
		if (this.getGtmSlaveIp() != null && !this.getGtmSlaveIp().equals("")){
			ret = checkSysUser(this.getGtmSlaveIp());
			if (ret != null) sb.append(ret+"\n");
		}
		if (nodeIpsList != null) {
			for (String nodeIp : nodeIpsList){
				ret = checkSysUser(nodeIp);
				if (ret != null) sb.append(ret+"\n");
			}
		}
		
		//set nodeIpList and nodeNumber if all check pass
		if (ret == null && nodeIpsList != null) {
			this.setNodeIpsList(nodeIpsList);
			this.setNodeNumber(nodeIpsList.size());
			
		}
		
		return sb.toString();
	}

	public  String 	checkClusterName() {

		if (this.getClusterName() == null) return null;
		SqlSession session = CommonValues.factory.openSession();
		int count = session.selectOne(ConfigNames.SELECT_CLUSTER_COUNT, this);
		session.close();
		if (count > 0){
			return this.getClusterName()+" exists!";
		} else {
			return null;
		}
	}
	
	public static String checkNodeIp(String nodeIp){
			
		if (!Validation.ipIsValid(nodeIp)){
			return "node ip : " + nodeIp + CommonValues.IPFORMATERROR;
		}
		if (!Validation.succeedsPing(nodeIp)){
			return "node ip : " +nodeIp +CommonValues.IPPINGERROR;
		}
		return null;
		
	}
	
	private void trimArray(String[] strArray){
		
		if (strArray == null) return ;
		for (int i = 0; i<strArray.length; i++){			
			if (strArray[i] != null) {
				strArray[i] = strArray[i].trim();	
			}
		}
		
	}

	private String checkSysUser(String ip){
		
		if (ip == null) return null;
		
//		//check SYSUSER if exist
//		String[] check_superuser_command =
//			{"sh", CommonValues.CHECK_OTHER_SUPERUSER_SH, ip, CommonValues.SYSUSER, this.getRootPassword()};
//        int ret = ExecShellCommand.execShellCommandWithReturn(check_superuser_command);
//        if (ret == 0) {
//        	    return "On " + ip +", sysUser: "+CommonValues.SYSUSER +" does not exist.";
//        }
        
        //check SYSUSER password if invalid
        String ret2 = checkPassword(ip,CommonValues.SYSUSER,this.getSysUserPassword());
		if (ret2 != null) return ret2;
        
        return null;
	}
	
	private String checkPassword(String ip,String user,String password){
//		if (ip == null) return null;
//		String[] check_password_command =
//	        {"sh", CommonValues.CHECK_PASSWORD_SH, ip, user,password};
//		int ret = ExecShellCommand.execShellCommandWithReturn(check_password_command);
//		if (ret != 0) {
//		   		return "On " + ip +", "+user+" password is invalid.";
//	    }
	    return null;
	}	
	
	public String checkNodes() {
		
		StringBuffer sb = new StringBuffer();
		String ret ;
		int OldNodeIpSize = this.getNodeIpsList().size();
		
		Set<String> ipSet = Sets.newHashSet(this.getNodeIpsList());
		
		if (this.getNodeIps() != null && !this.getNodeIps().equals("")){
			
			String[] ips = this.getNodeIps().split("\n");
			trimArray(ips);
			nodeIpsList = Lists.newArrayList();
			
			for (int i = 0; i<ips.length; i++){			
				if (ips[i] != null){
					
					// check ip format and ping
					ret = checkNodeIp(ips[i]);
					if (ret != null) sb.append(ret+"\n");
					
//					// check root password
//					ret = checkPassword(ips[i],"root",this.getRootPassword());
//					if (ret != null) sb.append(ret+"\n");
//					
					// check sysuser  and password
					ret = checkSysUser(ips[i]);
					if (ret != null) sb.append(ret+"\n");

					if ((ret = checkOtherIp(ips[i])) != null) sb.append(ret);
					
					nodeIpsList.add(ips[i]);
					ipSet.add(ips[i]);
					
				}
				
			}
			
			//check ip if unique
			if (ipSet.size() != nodeIpsList.size() + OldNodeIpSize) 
				sb.append(" all input ips are not unique or part of input ips exist!\n");		
			
			this.setNodeIpsList(nodeIpsList);
		}
		
		return sb.toString();
		
	}
	
	public String checkClients() {
		
		StringBuffer sb = new StringBuffer();
		String ret ;
		
		int OldNodeIpSize = this.getNodeIpsList().size();
		
		Set<String> ipSet = Sets.newHashSet(this.getNodeIpsList());
		
		if (this.getNodeIps() != null && !this.getNodeIps().equals("")){
			
			String[] ips = this.getNodeIps().split("\n");
			trimArray(ips);
			nodeIpsList = Lists.newArrayList();
			
			for (int i = 0; i<ips.length; i++){			
				if (ips[i] != null){
					
					// check ip format 
					if (!Validation.ipIsValid(ips[i])){
						sb.append("node ip : " + ips[i] + CommonValues.IPFORMATERROR +"\n");
					}
					
					if ((ret = checkOtherIp(ips[i])) != null) sb.append(ret);
					
					nodeIpsList.add(ips[i]);
					ipSet.add(ips[i]);
					
				}
				
			}
			
			//check ip if unique
			if (ipSet.size() != nodeIpsList.size() + OldNodeIpSize) 
				sb.append(" part of clients exist!\n");		
			
			this.setNodeIpsList(nodeIpsList);
		}
		
		return sb.toString();
		
	}
	
	private String checkOtherIp(String ip){
		
		if (this.getControllerIp()!=null && ip.equals(this.getControllerIp())) return ip +" is controller node!\n";
		if (this.getGtmMasterIp()!=null && ip.equals(this.getGtmMasterIp())) return ip +" is gtm master node!\n";
		if (this.getGtmSlaveIp()!=null && ip.equals(this.getGtmSlaveIp())) return ip +" is gtm slave node!\n";
		
		return null;
	}
	
	public List<String> getNodeIpsList() {
		return nodeIpsList;
	}
	public void setNodeIpsList(List<String> nodeIpsList) {
		this.nodeIpsList = nodeIpsList;
	}

	public String getNewNodeIp() {
		return newNodeIp;
	}
	public void setNewNodeIp(String newNodeIp) {
		this.newNodeIp = newNodeIp;
	}
	public String getControllerIp() {
		return controllerIp;
	}
	public void setControllerIp(String controllerIp) {
		this.controllerIp = controllerIp;
	}
	public String getRadioChoice() {
		return radioChoice;
	}
	public void setRadioChoice(String radioChoice) {
		this.radioChoice = radioChoice;
	}
	public String getDBSuperuserPassword() {
		return DBSuperuserPassword;
	}
	public void setDBSuperuserPassword(String dBSuperuserPassword) {
		DBSuperuserPassword = dBSuperuserPassword;
	}
	
}
